package com.ctshk.rpc.finance.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.SysApprovalType;
import com.ctshk.common.enums.SystemBusinessType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.CharUtil;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.booking.dto.SupplierOrderDTO;
import com.ctshk.rpc.booking.service.ISupplierOrderService;
import com.ctshk.rpc.custom.dto.trip.TripScheduleDTO;
import com.ctshk.rpc.custom.service.ICustomizedTripScheduleService;
import com.ctshk.rpc.finance.dto.special.SpecialCollectionDetailDTO;
import com.ctshk.rpc.finance.dto.special.SpecialCollectionListDTO;
import com.ctshk.rpc.finance.dto.special.SpecialTripScheduleDTO;
import com.ctshk.rpc.finance.dto.special.SupplierOrderSourceDTO;
import com.ctshk.rpc.finance.entity.FinanceSpecialCollection;
import com.ctshk.rpc.finance.entity.FinanceSpecialCollectionSource;
import com.ctshk.rpc.finance.json.FileJson;
import com.ctshk.rpc.finance.mapper.FinanceSpecialCollectionMapper;
import com.ctshk.rpc.finance.mapper.FinanceSpecialCollectionSourceMapper;
import com.ctshk.rpc.finance.req.special.*;
import com.ctshk.rpc.finance.service.IFinanceSpecialCollectionService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.tour.dto.schedule.SeriesTripScheduleDTO;
import com.ctshk.rpc.tour.service.ISeriesTripScheduleService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;


/**
 * <p>
 * 财务特殊收款 服务实现类
 * </p>
 *
 * @author 叶冠峰
 * @since 2021-04-05
 */
@DubboService
public class FinanceSpecialCollectionServiceImpl extends ServiceImpl<FinanceSpecialCollectionMapper, FinanceSpecialCollection> implements IFinanceSpecialCollectionService {

    @Autowired
    private FinanceSpecialCollectionMapper specialCollectionMapper;
    @Autowired
    private FinanceSpecialCollectionSourceMapper specialCollectionSourceMapper;
    /*@Autowired
    private RedisTemplate<String, Object> redisTemplate;*/

    @DubboReference
    private ISysApprovalService sysApprovalService;
    @DubboReference
    private ISysUserService sysUserService;
    @DubboReference
    private ISupplierOrderService supplierOrderService;
    @DubboReference
    private ICustomizedTripScheduleService customizedTripScheduleService;
    @DubboReference
    private ISeriesTripScheduleService seriesTripScheduleService;


    /**
     * 列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<SpecialCollectionListDTO>> list(SpecialCollectionListReq req) {
        Page<SpecialCollectionListDTO> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        Page<SpecialCollectionListDTO> page = specialCollectionMapper.queryListByCondition(iPage,req);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        page.getRecords().forEach(record -> {
//            UserDTO userDto = (UserDTO) redisTemplate.opsForValue().get(RedisConstants.ACCOUNT_QUERY_KEY + record.getCreateId());
            UserDTO userDto = sysUserService.queryCacheUser(record.getCreateId());
            if (userDto != null){
                record.setCreateUserName(userDto.getFullName());
                record.setCreateUserDept(userDto.getDept());
            }
        });
        PageResponse<SpecialCollectionListDTO> result = new PageResponse<>(
                page.getRecords(),
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 新增
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(SpecialCollectionAddReq req) {
        if (req.getIdList().size() == 0){
            throw new BusinessException(SystemError.SYS_428,"idList");
        }
        FinanceSpecialCollection collection = EntityUtil.copy(req,FinanceSpecialCollection.class);
        if (req.getFilesJson() != null && req.getFilesJson().size() > 0){
            collection.setFilesJson(JSON.toJSONString(req.getFilesJson()));
        }
        collection.setApprovalStatus(req.getType());
        LocalDateTime now = LocalDateTime.now();
        //操作类型（1 新增，2 修改）
        int operateType = 1;
        if (req.getId() == null){
            //新增
            collection.setId(SnowflakeIdWorker.nextId());
            //TSK+年後2位+月日4位+時分秒6位+4位随机数字
            String collectionNumber = "TSK"+ DateUtil.fmt(now,"yyMMddHHmmss")+ CharUtil.getRandomStr(4);
            collection.setCollectionNumber(collectionNumber);
            collection.setCreateId(req.getUserId());
            collection.setGmtCreate(now);
            collection.setIsDeleted(0);
        }else{
            operateType = 2;
            //修改
            if (!Objects.equals(collection.getApprovalStatus(),1) || !Objects.equals(collection.getApprovalStatus(),4)){
                throw new BusinessException(SystemError.FINANCE_BILL_17019);
            }
            collection.setModifiedId(req.getUserId());
        }
        //总收入金额
        BigDecimal totalCollectionAmount = BigDecimal.ZERO;
        List<FinanceSpecialCollectionSource> list = new ArrayList<>();
        for (CollectionSourceReq sourceReq : req.getIdList()){
            FinanceSpecialCollectionSource collectionSource = new FinanceSpecialCollectionSource();
            collectionSource.setId(SnowflakeIdWorker.nextId());
            collectionSource.setCollectionId(collection.getId());
            collectionSource.setGroupId(sourceReq.getId());
            //收款类型1 补贴，2 供应商预订单
            if (Objects.equals(req.getCollectionType(),1)){
                collectionSource.setSourceType(req.getSubsidySource());
            }else{
                collectionSource.setSourceType(3);
            }
            totalCollectionAmount = totalCollectionAmount.add(sourceReq.getCollectionAmount());
            //保存Json
        //    collectionSource.setGroupInfoJson(JSON.toJSONString(req.getIdList()));
            collectionSource.setCollectionAmount(sourceReq.getCollectionAmount());
            collectionSource.setCreateId(req.getUserId());
            collectionSource.setGmtCreate(now);
            collectionSource.setIsDeleted(0);
            list.add(collectionSource);
        }
        collection.setReceivedAmount(totalCollectionAmount);
        if (operateType == 1){
            boolean save = save(collection);
            if (!save){
                throw new BusinessException(SystemError.SYS_437);
            }
        }else{
            boolean update = updateById(collection);
            //清空收入来源
            Integer clean = specialCollectionSourceMapper.delByCollection(collection.getId(),req.getUserId());
            if (!update || clean <= 0){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        if (list.size() > 0){
            Integer batch = specialCollectionSourceMapper.insertBatchSomeColumn(list);
            if (batch < list.size()){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        if (Objects.equals(req.getType(),2)){
            //发起审批
            Long approvalId = startApproval(collection.getId(), collection.getId(), req.getUserId(),totalCollectionAmount);
            collection.setApprovalId(approvalId);
            collection.setApprovalStatus(2);
            boolean update = updateById(collection);
            if (!update){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        return Result.success(collection.getId());
    }

    /**
     * 详情
     *
     * @param req
     * @return
     */
    @Override
    public Result<SpecialCollectionDetailDTO> detail(SpecialCollectionIdReq req) {
        FinanceSpecialCollection collection = getById(req.getId());
        if (collection == null || Objects.equals(collection.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17020);
        }
        SpecialCollectionDetailDTO dto = EntityUtil.copy(collection,SpecialCollectionDetailDTO.class);
        if (StringUtils.isNotBlank(collection.getFilesJson())){
            List<FileJson> fileJsons = JSON.parseArray(collection.getFilesJson(), FileJson.class);
            dto.setFilesJson(fileJsons);
        }
        UserDTO userDto = sysUserService.queryCacheUser(collection.getCreateId());
        if (userDto != null){
            dto.setCreateUserName(userDto.getFullName());
            dto.setCreateUserDept(userDto.getDept());
        }
        QueryWrapper<FinanceSpecialCollectionSource> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("collection_id",collection.getId());
        queryWrapper.eq("is_deleted",0);
        List<FinanceSpecialCollectionSource> sourceList = specialCollectionSourceMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(sourceList)){
            //供应商预订单
            List<SupplierOrderSourceDTO> orderDTOList = new ArrayList<>();
            //定制报团
            List<SpecialTripScheduleDTO> tripScheduleDTOList = new ArrayList<>();
            sourceList.forEach(source -> {
                //收款类型1 补贴，2 供应商预订单
                if (Objects.equals(collection.getCollectionType(),2)){
                    Result<SupplierOrderDTO> result = supplierOrderService.selectListById(source.getGroupId());
                    SupplierOrderDTO orderDTO = result.getData();
                    if (result.isSuccess() && orderDTO != null){
                        SupplierOrderSourceDTO sourceDTOList = EntityUtil.copy(orderDTO, SupplierOrderSourceDTO.class);
                        sourceDTOList.setTotalFee(source.getCollectionAmount());
                        orderDTOList.add(sourceDTOList);
                    }
                }else{
                    //来源类型1 旅行团 2 定制包团 3 供应商预订单
                    if (Objects.equals(source.getSourceType(),1)){
                        //旅行团
                        SeriesTripScheduleDTO tripSchedule = seriesTripScheduleService.getTripScheduleId(source.getGroupId());
                        if (tripSchedule != null){
                            SpecialTripScheduleDTO scheduleDTO = new SpecialTripScheduleDTO();
                            scheduleDTO.setId(tripSchedule.getId());
                            scheduleDTO.setDepartureDate(tripSchedule.getDepartureDate());
                            scheduleDTO.setTripNumber(tripSchedule.getTripNumber());
                            scheduleDTO.setName(tripSchedule.getSeriesTripScheduleDataDTO().getTitle());
                            scheduleDTO.setDestination(tripSchedule.getSeriesTripScheduleDataDTO().getDestination());
                            scheduleDTO.setDepartureDateWeekDate(CharUtil.getWeekDay(tripSchedule.getDepartureDate().getDayOfWeek().getValue()));
                            scheduleDTO.setTravelDays(tripSchedule.getSeriesTripScheduleDataDTO().getTravelDays());
                            scheduleDTO.setNightDays(tripSchedule.getSeriesTripScheduleDataDTO().getNightDays());
                            tripScheduleDTOList.add(scheduleDTO);
                        }
                    }else if (Objects.equals(source.getSourceType(),2)){
                        //定制包团
                        TripScheduleDTO tripScheduleDTO = customizedTripScheduleService.queryById(source.getGroupId());
                        if (tripScheduleDTO != null){
                            SpecialTripScheduleDTO scheduleDTO = EntityUtil.copy(tripScheduleDTO,SpecialTripScheduleDTO.class);
                            scheduleDTO.setDepartureDate(tripScheduleDTO.getDepartureDate().toLocalDate());
                            tripScheduleDTOList.add(scheduleDTO);
                        }
                    }
                }
            });
            //收款类型1 补贴，2 供应商预订单
            if (Objects.equals(collection.getCollectionType(),1)){
                //补贴来源类型1 旅行团，2 定制包团
                if (Objects.equals(collection.getSubsidySource(),1)){
                    //旅行团
                    dto.setScheduleList(tripScheduleDTOList);
                }else{
                    //定制包团
                    dto.setScheduleList(tripScheduleDTOList);
                }
            }else if (Objects.equals(collection.getCollectionType(),2)){
                dto.setSourceList(orderDTOList);
            }
        }
        return Result.success(dto);
    }

    /**
     * 删除
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result del(SpecialCollectionIdReq req) {
        FinanceSpecialCollection collection = getById(req.getId());
        if (collection == null || Objects.equals(collection.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17020);
        }
        if (!Objects.equals(collection.getApprovalStatus(),4)){
            throw new BusinessException(SystemError.FINANCE_BILL_17021);
        }
        collection.setIsDeleted(1);
        collection.setModifiedId(req.getUserId());
        boolean update = updateById(collection);
        //批量删除明细
        Integer batch = specialCollectionSourceMapper.delByCollection(collection.getId(),req.getUserId());
        if (!update || batch <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(collection.getId());
    }

    /**
     * 提交审批
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result toApproval(SpecialCollectionIdReq req) {
        FinanceSpecialCollection collection = getById(req.getId());
        if (collection == null || Objects.equals(collection.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17020);
        }
        if (!Objects.equals(collection.getApprovalStatus(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17019);
        }
        //发起审批
        Long approvalId = startApproval(collection.getId(), collection.getId(), req.getUserId(),collection.getReceivedAmount());
        collection.setApprovalId(approvalId);
        collection.setApprovalStatus(2);
        collection.setModifiedId(req.getUserId());
        boolean update = updateById(collection);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(collection.getId());
    }

    /**
     * 审批
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result approval(SpecialCollectionApprovalReq req) {
        QueryWrapper<FinanceSpecialCollection> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("approval_id",req.getApprovalId());
        queryWrapper.eq("is_deleted",0);
        FinanceSpecialCollection collection = specialCollectionMapper.selectOne(queryWrapper);
        if (collection == null){
            throw new BusinessException(SystemError.FINANCE_BILL_17020);
        }
        if (!Objects.equals(collection.getApprovalStatus(),2)){
            throw new BusinessException(SystemError.FINANCE_BILL_17019);
        }
        collection.setApprovalStatus(req.getType());
        collection.setModifiedId(req.getUserId());
        boolean update = updateById(collection);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        Result<ApprovalCheckDTO> check = sysApprovalService.check(req.getApprovalId(), req.getUserId(), req.getType(), req.getComments());
        if (check == null || !check.getData().getIsFinish()){
            throw new BusinessException(SystemError.SYS_437);
        }
        if (Objects.equals(req.getType(),3)){
            //TODO 审批通过的处理

        }
        return Result.success(collection.getId());
    }


    /**
     * 发起审批流程
     * @param id
     * @param businessId
     * @param userId
     * @param amount
     */
    private Long startApproval(Long id, Long businessId, Long userId,BigDecimal amount) {
        Map<String, Object> extendParams = new HashMap<>();
        extendParams.put("id", id);
        try{
            Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.FINANCE.getCode(),
                    SysApprovalType.PAYMENT_PAYMENT_FINANCE.getCode(), businessId,
                    userId, amount, JSON.toJSONString(extendParams));
            if (!approvalResult.isSuccess()) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4044);
            }
            return approvalResult.getData().getApprovalId();
        }catch (Exception e){
            throw new BusinessException(SystemError.SYS_422);
        }
    }


}
